﻿using QMesSocketLib;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace QMesSocketServer
{
    class Program
    {
        static string ip = "127.0.0.1";
        static int port = 9002;
        const int BufferSize = 1000000;
        static string path = Environment.CurrentDirectory + "\\QMesFiles";
        int _ReceiveTimeout = 30000;
        int _SnedTimeout = 30000;


        [DllImport("User32.dll ", EntryPoint = "FindWindow")]
        private static extern int FindWindow(string lpClassName, string lpWindowName);

        [DllImport("user32.dll ", EntryPoint = "GetSystemMenu")]
        extern static IntPtr GetSystemMenu(IntPtr hWnd, IntPtr bRevert);

        [DllImport("user32.dll ", EntryPoint = "RemoveMenu")]
        extern static int RemoveMenu(IntPtr hMenu, int nPos, int flags);


        //static MenuItem exititem = new MenuItem("退出", item1_Click);
        //static MenuItem showitem = new MenuItem("显示", item1_Click);
        static void Main(string[] args)
        {
            try
            {
                try
                {
                    //与控制台标题名一样的路径
                    string fullPath = System.Environment.CurrentDirectory + "\\QMesSocketServer.exe";
                    //根据控制台标题找控制台
                    int WINDOW_HANDLER = FindWindow(null, fullPath);
                    //找关闭按钮
                    IntPtr CLOSE_MENU = GetSystemMenu((IntPtr)WINDOW_HANDLER, IntPtr.Zero);
                    int SC_CLOSE = 0xF060;
                    //关闭按钮禁用
                    RemoveMenu(CLOSE_MENU, SC_CLOSE, 0x0);
                }
                catch(Exception ex)
                {
                    Log.LogError(ex);
                }


                string address = Settings.GetSocketServerAddress();
                port = Settings.GetSocketServerPort();
                if (!string.IsNullOrWhiteSpace(address)) ip = address;
                if (port <= 1024) port = 9002;
                Console.Title = "QMes附件服务器 " + ip + ":" + port.ToString();


                IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Parse(ip), port);
                Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                sock.Bind(ipEndPoint);
                sock.Listen(1);
                Console.WriteLine(DateTime.Now.ToString() + " 监听开始: " + ip.ToString() + ":" + port.ToString());


                while (true)
                {
                    Socket client = sock.Accept();
                    if (client.Connected)
                    {
                        Thread cThread = new Thread(new ParameterizedThreadStart(myClient));
                        cThread.IsBackground = true;
                        cThread.Start(client);
                    }
                }
            }
            catch(Exception ex)
            {
                Log.LogError(ex);
                Console.WriteLine(ex.Message);
            }
        }


        static void myClient(object oSocket)
        {
            Socket clientSocket = (Socket)oSocket;
            string clientName = clientSocket.RemoteEndPoint.ToString();
            Console.WriteLine(DateTime.Now.ToString() + " 新来一个客户端:" + clientName);
            try
            {
                string tempPath = path;
                byte[] buffer = new byte[BufferSize];
                int count = clientSocket.Receive(buffer);
                Console.WriteLine(DateTime.Now.ToString() + " 收到" + clientName + ":" + Encoding.Default.GetString(buffer, 0, count));

                string receiveStr = Encoding.Default.GetString(buffer, 0, count);
                MessageEntity receiveMsg = receiveStr.ToObject<MessageEntity>();
                if (receiveMsg == null)
                {
                    string error = string.Format("字符串 {0} 无法转换为消息实体", receiveStr);
                    Log.LogMessage(error);
                    Console.WriteLine(error);
                    return;
                }

                if (!string.IsNullOrWhiteSpace(receiveMsg.FormName))
                    tempPath += "\\" + receiveMsg.FormName;
                if (!string.IsNullOrWhiteSpace(receiveMsg.BillNo))
                    tempPath += "\\" + receiveMsg.BillNo;


                if (receiveMsg.Type == EnumLib.SocketType.Upload)
                {
                    #region 上传
                    if (!Directory.Exists(tempPath))
                        Directory.CreateDirectory(tempPath);

                    MessageEntity sendMsg = new MessageEntity();
                    sendMsg.Type = EnumLib.SocketType.ReadyToSendFile;
                    clientSocket.Send(Encoding.Default.GetBytes(sendMsg.ToJson()));
                    long receive = 0L;
                    Console.WriteLine(DateTime.Now.ToString() + " 正在接收文件:" + receiveMsg.File.FileName + "...");
                    using (FileStream writer = new FileStream(Path.Combine(tempPath, receiveMsg.File.FileName), FileMode.Create, FileAccess.Write, FileShare.None))
                    {
                        int received;
                        while (receive < receiveMsg.File.FileLength)
                        {
                            received = clientSocket.Receive(buffer);
                            writer.Write(buffer, 0, received);
                            writer.Flush();
                            receive += (long)received;
                        }
                        writer.Close();
                    }
                    Console.WriteLine(DateTime.Now.ToString() + " Receive finish.\n");
                    #endregion
                }
                else if (receiveMsg.Type == EnumLib.SocketType.DownLoad)
                {
                    #region 下载
                    long send = 0L;
                    string fileName2 = Path.Combine(tempPath, receiveMsg.File.FileName);

                    using (FileStream reader = new FileStream(fileName2, FileMode.Open, FileAccess.Read, FileShare.None))
                    {
                        MessageEntity sendMsg = new MessageEntity();
                        sendMsg.Type = EnumLib.SocketType.ReadyToSendFile;
                        sendMsg.File.FileLength = reader.Length;
                        clientSocket.Send(Encoding.Default.GetBytes(sendMsg.ToJson()));
                        //clientSocket.Send(Encoding.Default.GetBytes("OK," + reader.Length.ToString()));
                        byte[] fileBuffer = new byte[BufferSize];
                        int read, sent;
                        while ((read = reader.Read(fileBuffer, 0, BufferSize)) != 0)
                        {
                            sent = 0;
                            while ((sent += clientSocket.Send(fileBuffer, sent, read, SocketFlags.None)) < read)
                            {
                                send += (long)sent;
                            }
                        }

                        reader.Close();
                    }
                    #endregion
                }
                else if (receiveMsg.Type == EnumLib.SocketType.FileList)
                {
                    #region 文件列表
                    List<FileEntity> list = new List<FileEntity>();

                    if (Directory.Exists(tempPath))
                    {
                        string[] files = Directory.GetFiles(tempPath);
                        if (files != null && files.Length > 0)
                        {
                            foreach (string file in files)
                            {
                                FileEntity f = new FileEntity();
                                f.FileName = Path.GetFileName(file);
                                list.Add(f);
                            }


                            clientSocket.Send(Encoding.Default.GetBytes(list.ToJson()));
                        }
                    }
                    
                    clientSocket.Send(Encoding.Default.GetBytes(list.ToJson()));
                    
                    #endregion
                }
                else if (receiveMsg.Type == EnumLib.SocketType.Delete)
                {
                    #region 删除
                    long send = 0L;
                    string fileName2 = Path.Combine(tempPath, receiveMsg.File.FileName);
                    if (File.Exists(fileName2))
                        File.Delete(fileName2);

                    Log.LogMessage("删除文件：" + fileName2);
                    #endregion
                }

            }
            catch (Exception ex)
            {
                Log.LogError(ex);
                Console.WriteLine(DateTime.Now.ToString() + " 客户端异常:" + clientName + "退出：" + ex.Message);
                try
                {
                    clientSocket.Close();
                }
                catch { }
            }

        }
    }
}
